<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[1.23]-请求和响应：GET和POST两者皆可得及超越JSON格式返回 | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[1.23]-请求和响应：GET和POST两者皆可得及超越JSON格式返回，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong>PhalApi</strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="http://qa.phalapi.net/">社区</a></li>
                    <li><a href="/download.html">下载</a></li>
                    <li class="active"><a href="/wikis/">文档</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/">体验</a></li>
                    <li><a href="/about.html">关于</a></li>
                    <li><a href="/donate.html">贡献</a></li>
                    <li><a href="/wikis/en/">English</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B1.22%5D-%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81%EF%BC%9A%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AD%BE%E5%90%8D%E8%A7%84%E5%88%99.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.24%5D-%E7%BC%93%E5%AD%98%E7%AD%96%E7%95%A5%EF%BC%9A%E6%9B%B4%E7%81%B5%E6%B4%BB%E5%9C%B0%E5%8F%AF%E9%85%8D%E7%BD%AE%E5%8C%96%E7%9A%84%E5%A4%9A%E7%BA%A7%E7%BC%93%E5%AD%98.html">下一章</a></h4>
<hr />
<h2>1.23.1 请求</h2>
<p>把我们后台的API想象成一个函数，那么请求的参数就是我们的参数列表；而接口响应的数据则对应函数返回的结果。  </p>
<p>对于请求，正如前面所看到的，我们可以使用$_GET，也可以使用$_POST，也可以两者都使用，还可以在测试时自己指定模拟的请求数据包。  </p>
<p>或者，在实际项目开发中，我们还需要根据自身的需求，跟我们自己的客户端作一些约定。如通常地，我们会要求客户端 <strong>service参数必须用GET方式</strong> ，以便服务器返回500时定位接口服务位置。对此，简单的我们把$_POST['service']去掉即可，如在入口文件前面添加：</p>
<pre><code class="language-php">unset($_POST['service']);   //只接收GET方式的service参数</code></pre>
<h3>(1) 在index.php入口处指定数据源</h3>
<p>很多时间，不同的项目对数据接收有不同的需求。如简单地，强制统一使用$_POST参数，我们可以这样在入口处进行代码调整：</p>
<pre><code class="language-php">//vim ./index.php

DI()-&gt;request = new PhalApi_Request($_POST); </code></pre>
<p>对于复杂的情况，如需要使用post_raw数据，则可以继承<code>PhalApi_Request</code>实现相应的数据源解析。如：  </p>
<pre><code>class My_Request extends PhalApi_Request{
    public function __construct($data = NULL) {
        parent::__construct($data);

        // json处理
        $this-&gt;post = json_decode(file_get_contents('php://input'), TRUE);    

        // 普通xml处理
        $this-&gt;post = simplexml_load_string (
            file_get_contents('php://input'),
            'SimpleXMLElement',
            LIBXML_NOCDATA
        );
        $this-&gt;post = json_decode(json_encode($this-&gt;post), TRUE);
    }  
}</code></pre>
<p>然后在子类实现对各类参数的数据源的准备。可以说，<code>PhalApi_Request::__construct()</code>构造函数用于初始化各类辅助侯选的数据源，而<code>PhalApi_Request::getData()</code>则用于生成主要默认的数据源。  </p>
<h3>(2) 单元测试时指定数据源</h3>
<p>在进行单元测试时，我们需要模拟接口的请求动作，也需要提供接口参数。这时的参数的指定更为灵活。可通过以下代码来实现，即：  </p>
<pre><code class="language-php">//数据源
$data = array(...);

DI()-&gt;request = new PhalApi_Request($data);</code></pre>
<p>或者使用PhalApi封装的测试类来快速模拟调用接口：  </p>
<pre><code>    public function testIndexByRunner()
    {
        //Step 1. 构建请求URL
        $url = 'service=Default.Index&amp;username=dogstar';
        $params = array();

        //Step 2. 执行请求  
        $rs = PhalApi_Helper_TestRunner::go($url, $params);
    }</code></pre>
<h3>(3) 接口数据的加密传送</h3>
<p>有时，出于安全性的考虑，项目需要对请求的接口参数进行对称加密传送。这时可以通过重载PhalApi_Request::genData()来轻松实现。<br />
假设，我们现在需要把全部的参数base64编码序列化后通过$_POST['data']来传递，则相应的解析代码如下。  </p>
<p>第一步，先定义自己的扩展请求类，在里面完成对称解析的动作：  </p>
<pre><code class="language-php">&lt;?php

class Common_Request extends PhalApi_Request {

    public function genData($data) {
        if (!isset($data) || !is_array($data)) {
            $data = $_POST; //改成只接收POST
        }

        return isset($data['data']) ? base64_decode($data['data']) : array();
    }
}</code></pre>
<p>第二步，在index.php入口文件中重新注册请求类（即添加以下代码）：  </p>
<pre><code class="language-php">//重新注册request
DI()-&gt;request = 'Common_Request'; </code></pre>
<p>然后，就可以轻松实现了接口参数的对称加密传送。<br />
至此，你也许已经发现：指定数据源和对称加密是可以结合来使用的。  </p>
<h3>(4) 接口参数级别的数据源</h3>
<p>除了可以指定全局的接口数据源外，还可以进行更细致的配置，即为某个接口参数指定使用$GET、$_POST、$_COOKIE、$_SERVER、$_REQUEST或头部等其他数据源。  </p>
<p>其使用方式是在配置接口参数规则时，使用source配置来指定当前参数的数据源，如指定用户在登录时，用户名使用$_GET、密码使用$_POST。  </p>
<pre><code class="language-php">public function getRules() {
    return array(
        'login' =&gt; array(
            'username' =&gt; array('name' =&gt; 'username', 'source' =&gt; 'get'),
            'password' =&gt; array('name' =&gt; 'password', 'source' =&gt; 'post'),
        ),  
    );
}</code></pre>
<p>这样，PhalApi框架就会从$_GET中提取<code>username</code>参数，从$_POST中提取<code>password</code>参数。  </p>
<p>目前支持的source与对应的数据源映射关系如下：  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>source</th>
<th>对应的数据源</th>
</tr>
</thead>
<tbody>
<tr>
<td>post</td>
<td>$_POST</td>
</tr>
<tr>
<td>get</td>
<td>$_GET</td>
</tr>
<tr>
<td>cookie</td>
<td>$_COOKIE</td>
</tr>
<tr>
<td>server</td>
<td>$_SERVER</td>
</tr>
<tr>
<td>requset</td>
<td>$_REQUEST</td>
</tr>
<tr>
<td>header</td>
<td>$_SERVER['HTTP_X']</td>
</tr>
</tbody>
</table>
<p>因此，这样就可以轻松、更自由获取不同来源的参数。以下是一些常用的配置示例。  </p>
<pre><code class="language-php">// 获取HTTP请求方法，判断是POST还是GET
'method' =&gt; array('name' =&gt; 'REQUEST_METHOD', 'source' =&gt; 'server'),

// 获取COOKIE中的标识
'is_new_user' =&gt; array('name' =&gt; 'is_new_user', 'source' =&gt; 'cookie'),

// 获取HTTP头部中的编码，判断是否为utf-8
'charset' =&gt; array('name' =&gt; 'Accept-Charset', 'source' =&gt; 'header'),</code></pre>
<p>若需要扩展项目自定义的映射关系，则可以重载<code>PhalApi_Request::getDataBySource($source)</code>方法，如：  </p>
<pre><code>class My_Request extends PhalApi_Request {
    protected function &amp;getDataBySource($source) {
        if (strtoupper($source) == 'stream') {
            // TODO 处理二进制流
        }

        return parent::getDataBySource($source);
    }
}</code></pre>
<p>然后，便可在项目中这样配置使用二进制流的数据源。  </p>
<pre><code class="language-php">// 从二进制流中获取密码
'password' =&gt; array('name' =&gt; 'password', 'source' =&gt; 'stream'),</code></pre>
<p>若配置的source为无效或非法时，则会抛出异常。<br />
如故意配置一个错误的数据源source为NOT_FOUND。 </p>
<pre><code class="language-php">'password' =&gt; array('name' =&gt; 'password', 'source' =&gt; 'NOT_FOUND'),</code></pre>
<p>在请求接口时，会遇到这样的异常提示返回。  </p>
<pre><code>{
    "ret": 500,
    "data": [],
    "msg": "服务器运行错误: 参数规则中未知的数据源：NOT_FOUND"
}</code></pre>
<blockquote>
<p>温馨提示：以上功能需要PhalApi 1.4.0 及以上版本支持。  </p>
</blockquote>
<h2>1.23.2 响应</h2>
<p>当前默认使用JSON的格式返回，但项目需要其他返回格式也是可以的。只需要实现PhalApi_Response抽象中的formatResult($result)格式化返回结果，然后也是重新注册DI()-&gt;response服务即可。如：  </p>
<h3>(1) JSONP的返回</h3>
<p>在H5页面中，我们可能会需要用到JSONP的返回，所以这里默认提供了这种格式的支持。  </p>
<p>在入口文件中，添加：</p>
<pre><code class="language-php">//支持JsonP的返回
if (!empty($_GET['callback'])) {
    DI()-&gt;response = new PhalApi_Response_JsonP($_GET['callback']);
}</code></pre>
<p>在接口访问时再带上&amp;callback=XXX参数即可。  </p>
<p>这里在创建响应服务时，可以看到是用了回调函数的名字进行初始化。考虑到会存在XSS（跨站脚本攻击），对回调函数要进行相应的过滤，可以用黑名单或者白名单的方式。黑名单方式暂时还没提供，白名单相对简单但需要项目自己实现，如：</p>
<pre><code class="language-php">class Common_JsonP extends PhalApi_Response_JsonP {

    protected function clearXss($callback) {
        return in_array($callback, array('fun1', 'func2', 'func3')) ? $callback : '';
    }
}</code></pre>
<h3>(2) 其他格式返回</h3>
<p>如上面所述，当需要返回一种当前PhalApi没提供的格式时，可以：</p>
<ul>
<li>1、实现PhalApi_Response抽象中的formatResult($result)格式化返回结果</li>
<li>2、重新注册DI()-&gt;response服务  </li>
</ul>
<p>这里以扩展XML返回格式为例，简单说明。  </p>
<p>首先，添加实现一个XML响应子类：</p>
<pre><code class="language-php">&lt;?php

class Common_Response_XML extends PhalApi_Response {

    protected function formatResult($result) {
        return ArrayToXML::toXml($result);
    }
}</code></pre>
<p>关于ArrayToXML，请查看： <a href="http://www.oschina.net/code/snippet_54100_1548">将PHP数组转成XML</a>  </p>
<p>然后，重新注册：</p>
<pre><code class="language-php">DI()-&gt;response = new Common_Response_XML();</code></pre>
<p>done!</p>
<hr />
<h4><a href="/wikis/%5B1.22%5D-%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81%EF%BC%9A%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AD%BE%E5%90%8D%E8%A7%84%E5%88%99.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.24%5D-%E7%BC%93%E5%AD%98%E7%AD%96%E7%95%A5%EF%BC%9A%E6%9B%B4%E7%81%B5%E6%B4%BB%E5%9C%B0%E5%8F%AF%E9%85%8D%E7%BD%AE%E5%8C%96%E7%9A%84%E5%A4%9A%E7%BA%A7%E7%BC%93%E5%AD%98.html">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <span>友情链接:</span>
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <a href="http://www.oschina.net/" target="_blank"> 开源中国 </a>
                    <a href="https://www.itran.cc/" target="_blank">艾翻译</a>
                    <a href="http://www.phalconphp.com/en/" target="_blank">Phalcon</a>
                    <a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" target="_blank">PHPUnit</a>
                    <a href="http://www.thoughtworks.com/cn/" target="_blank">ThoughtWorks</a>
                    <a href="mailto:chanzonghuang@gmail.com">友链交换</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
                    <a href="https://jq.qq.com/?_wv=1027&k=4A6reum"><img src="../images/qq.png"  alt="qq" /></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>